
#include "stdafx.h"
#include "viewer.h"

using namespace Blox;

//#ifdef USE_DIRECTX
//// This is causes the required libraries to be linked in, the same thing can be accomplished by
//// adding it to your compiler's link list (Project->Settings->Link in VC++),
//// but I prefer this method.
//#pragma comment(lib,"d3d9.lib")
//#pragma comment(lib,"dxerr9.lib")
//#endif //USE_DIRECTX

//////////////////////////////////////////////////////////////////////////

bool Viewer::Init( HWND hWnd )
{
	m_hWnd = hWnd;

	// Console.
	//if( !InitConsole() )
	//	return false;

	// DirectX
	if( !InitCanvas() )
		return false;

	// Input
	if( !InitInput() )
		return false;

	// Camera
	if( !InitCamera() )
		return false;

	// Blox.
	if( !InitBlox() )
		return false;

	return true;
}

void Viewer::Clean()
{
	CleanCanvas();

	CleanConsole();
}

//////////////////////////////////////////////////////////////////////////

bool Viewer::InitConsole()
{
	// Set up the Console.
	enum { MAX_CONSOLE_LINES = 500 };

	int hConHandle;
	long lStdHandle;

	CONSOLE_SCREEN_BUFFER_INFO coninfo;
	FILE *fp;

	// allocate a console for this app
	AllocConsole();

	// set the screen buffer to be big enough to let us scroll text
	GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
	coninfo.dwSize.Y = MAX_CONSOLE_LINES;
	SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);

	// redirect unbuffered STDOUT to the console
	lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
	hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
	fp = _fdopen( hConHandle, "w" );
	*stdout = *fp;
	setvbuf( stdout, NULL, _IONBF, 0 );

	// redirect unbuffered STDIN to the console
	lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
	hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
	fp = _fdopen( hConHandle, "r" );
	*stdin = *fp;
	setvbuf( stdin, NULL, _IONBF, 0 );

	// redirect unbuffered STDERR to the console
	lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
	hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
	fp = _fdopen( hConHandle, "w" );
	*stderr = *fp;
	setvbuf( stderr, NULL, _IONBF, 0 );

	// make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog point to console as well
	std::ios::sync_with_stdio();

	return true;
}

bool Viewer::InitBlox()
{
	// Clear the existing block map.
	delete m_pBlockMap;
	m_pBlockMap = NULL;

	{
		// Set up bounds.
		Bounds bounds( Vec(-100.0f,-100.0f,-100.0f), Vec(100.0f,100.0f,100.0f) );

		// Set up Map.
		m_pBlockMap = new Blox::Map();
		m_pBlockMap->Init( bounds );
	}

	return true;
}

bool Viewer::InitCanvas()
{
	CleanCanvas();

#ifdef USE_DIRECTX
	m_pCanvas = new Canvas_D3D();
	if( m_pCanvas )
	{
		Canvas_D3D::InitData setup;
		setup.hWnd = m_hWnd;
		setup.uWidth = 640;
		setup.uHeight = 480;
		setup.uFPS = 60;
		setup.uTriBufferSize = 1024;
		setup.uLineBufferSize = 2048;
		setup.uModelBufferSize = 2048;
		if( !m_pCanvas->Init(&setup) )
		{
			return false;
		}
	}
#else
	m_pCanvas = new Canvas_2D();
	//m_pCanvas
#endif //USE_DIRECTX

	Blox::Canvas::SetDefaultCanvas(m_pCanvas);
	Blox::Canvas::LoadDefaultModels();

	return m_pCanvas!=NULL;
}

bool Viewer::InitInput()
{
	return m_xInput.Init();
}

bool Viewer::InitCamera()
{
	m_xInput.RegisterAction( InputHandler::Action( 'W', 0, (u8)InputHandler::ACTION_DOWN, InputAction_CamMoveForward, &m_xMain3D.GetCamera() ) );
	m_xInput.RegisterAction( InputHandler::Action( 'A', 0, (u8)InputHandler::ACTION_DOWN, InputAction_CamMoveLeft, &m_xMain3D.GetCamera() ) );
	m_xInput.RegisterAction( InputHandler::Action( 'S', 0, (u8)InputHandler::ACTION_DOWN, InputAction_CamMoveBack, &m_xMain3D.GetCamera() ) );
	m_xInput.RegisterAction( InputHandler::Action( 'D', 0, (u8)InputHandler::ACTION_DOWN, InputAction_CamMoveRight, &m_xMain3D.GetCamera() ) );
	m_xInput.RegisterAction( InputHandler::Action( 'Q', 0, (u8)InputHandler::ACTION_DOWN, InputAction_CamMoveUp, &m_xMain3D.GetCamera() ) );
	m_xInput.RegisterAction( InputHandler::Action( 'E', 0, (u8)InputHandler::ACTION_DOWN, InputAction_CamMoveDown, &m_xMain3D.GetCamera() ) );

	m_xInput.RegisterAction( InputHandler::Action( VK_RETURN, 0, (u8)InputHandler::ACTION_RELEASED, InputAction_SplitBlock, &m_pBlockMap ) );

	return true;
}

//////////////////////////////////////////////////////////////////////////

void Viewer::CleanConsole()
{

}

void Viewer::CleanCanvas()
{
	if( m_pCanvas )
	{
		m_pCanvas->Clean();
		delete m_pCanvas;
		m_pCanvas = NULL;
	}
}

//////////////////////////////////////////////////////////////////////////

void Viewer::Process()
{
	m_xInput.Process();
	m_xMain3D.SetClearCol( Col::BLACK );
}

//////////////////////////////////////////////////////////////////////////

void Viewer::Render()
{
	if( m_pCanvas )
	{
		m_pBlockMap->Draw();

		m_pCanvas->Render( m_xMain3D );
	}
}

void Viewer::HandleInput()
{
	
}

void Viewer::InputAction_CamMoveForward( void * pData )
{
	Camera* pCam = (Camera*)pData;
	pCam->MoveForward(1.0f);
}

void Viewer::InputAction_CamMoveBack( void * pData )
{
	Camera* pCam = (Camera*)pData;
	pCam->MoveForward(-1.0f);
}

void Viewer::InputAction_CamMoveLeft( void * pData )
{
	Camera* pCam = (Camera*)pData;
	pCam->MoveRight(-1.0f);
}

void Viewer::InputAction_CamMoveRight( void * pData )
{
	Camera* pCam = (Camera*)pData;
	pCam->MoveRight(1.0f);
}

void Viewer::InputAction_CamMoveUp( void * pData )
{
	Camera* pCam = (Camera*)pData;
	pCam->MoveUp(1.0f);
}

void Viewer::InputAction_CamMoveDown( void * pData )
{
	Camera* pCam = (Camera*)pData;
	pCam->MoveUp(-1.0f);
}

void Viewer::InputAction_SplitBlock( void * pData )
{
	Map* pMap = *((Map**)pData);
	AABB obj( Vec(20.0f,15.0f,61.0f), Vec(1.0f,1.0f,1.0f) );

	Block * pBlock = pMap->GetSmallestEncompassingBlock( obj );

	pBlock->Split();
	
}


